package algo3.algothief.modelo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;


public abstract class EstadoDelJuego {
	
	protected static String stringCaracteristico;
	
	protected String estado;
	protected Juego juego;
	
//-------------------------------------------------------------------------------------
	
	public EstadoDelJuego(String estado, Juego juego) {
		this.estado = estado;
		this.juego = juego;
	}

//-------------------------------------------------------------------------------------
	
	public Element serializar(Document doc) {
		Element elementoEstado = doc.createElement("EstadoDelJuego");
		elementoEstado.setAttribute("tipoDeEstado", this.verStringCaracteristico());
		
		return elementoEstado;
	}
		
	public static EstadoDelJuego hidratar(Document doc, Juego juegoActual) {
		Element elementoEstado = (Element)doc.getElementsByTagName("EstadoDelJuego").item(0);
		String stringCaracteristicoNuevo = elementoEstado.getAttribute("tipoDeEstado");
		
		EstadoDelJuego estadoNuevo = EstadoDelJuego.verEstadoConStringCaracteristico(stringCaracteristicoNuevo, juegoActual);
				
		return estadoNuevo;
	}
	
//-------------------------------------------------------------------------------------
	
	protected static HashMap<String, EstadoDelJuego> crearPosiblesEstados(Juego juegoActual) {
		HashMap<String, EstadoDelJuego> posiblesEstados = new HashMap<String, EstadoDelJuego>();
		
		EstadoDelJuego juegoEnCurso = new JuegoEnCurso(juegoActual);
		
		EstadoDelJuego juegoEnCursoConOrdenDeArresto = new JuegoEnCursoConOrdenDeArresto(juegoActual);
		EstadoDelJuego seLlegoAlUltimoPais = new SeLlegoAlUltimoPais(juegoActual);
		EstadoDelJuego seLlegoAlUltimoPaisConOrdenDeArresto = new SeLlegoAlUltimoPaisConOrdenDeArresto(juegoActual);
		
		EstadoDelJuego seAcaboElTiempo = new SeAcaboElTiempo(juegoActual);
		EstadoDelJuego seAtrapoAlLadron = new SeAtrapoAlLadron(juegoActual);
		EstadoDelJuego seEscapoElLadronPorNoTenerOrdenDeArresto = new SeEscapoElLadronPorNoTenerOrdenDeArresto(juegoActual);
		
		posiblesEstados.put(juegoEnCurso.verStringCaracteristico(), juegoEnCurso);
		posiblesEstados.put(juegoEnCursoConOrdenDeArresto.verStringCaracteristico(), juegoEnCursoConOrdenDeArresto);
		posiblesEstados.put(seLlegoAlUltimoPais.verStringCaracteristico(), seLlegoAlUltimoPais);
		posiblesEstados.put(seLlegoAlUltimoPaisConOrdenDeArresto.verStringCaracteristico(), seLlegoAlUltimoPaisConOrdenDeArresto);
		posiblesEstados.put(seAcaboElTiempo.verStringCaracteristico(), seAcaboElTiempo );
		posiblesEstados.put(seAtrapoAlLadron .verStringCaracteristico(), seAtrapoAlLadron );
		posiblesEstados.put(seEscapoElLadronPorNoTenerOrdenDeArresto.verStringCaracteristico(), seEscapoElLadronPorNoTenerOrdenDeArresto);
		
		return posiblesEstados;
	}
	
	protected static EstadoDelJuego verEstadoConStringCaracteristico(String stringCaracteristicoNuevo, Juego juegoActual) {
		HashMap<String, EstadoDelJuego> posiblesEstados = EstadoDelJuego.crearPosiblesEstados(juegoActual);
		EstadoDelJuego estado = posiblesEstados.get(stringCaracteristicoNuevo);
		
		return estado;
	}
	
//-------------------------------------------------------------------------------------
	
	public abstract ArrayList<Pais> verHaciaQuePaisesSePuedeViajar();
	
	public abstract HashMap<String, LugarDePais> verQueLugaresSePuedenVisitar();
	
	public abstract boolean modificarLaDescripcionDelSospechoso(HashMap<String, String> caracteristicasElegidasPorElJugador);
	
	public abstract boolean emitirOrdenDeArresto();
	
	public abstract boolean viajarA(Pais pais) throws ParserConfigurationException, SAXException, IOException;
	
	public abstract String visitar(LugarDePais lugar);
	
	public abstract boolean verSiSePuedeSeguirJugando();
	
	public abstract EstadoDelJuego comprobarPosibleCambioDeEstadoACausaDelTiempo(Tiempo tiempo);
	
	public abstract EstadoDelJuego modificarEstadoACausaDeLlegarAlUltimoPais();
	
	public abstract EstadoDelJuego modificarEstadoACausaDeSalirDelUltimoPais();
	
	public abstract EstadoDelJuego modificarEstadoACausaDeEmitirOrdenDeArresto();
	
	public abstract EstadoDelJuego comprobarPosibleCambioDeEstadoAlVisitarUnLugar(Caso caso, CuartelGeneral cuartel, LugarDePais lugar);
	
//-------------------------------------------------------------------------------------

	protected abstract String verStringCaracteristico();

//-------------------------------------------------------------------------------------
	
	public String verMensajeInformativoDelEstado() {
		return this.estado;
	}
	
	public void actualizarJuego(Juego juegoActual) {
		this.juego = juegoActual;
	}
}
